package com.hhdz.barrage.service;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.support.annotation.Nullable;
import android.widget.Toast;

import com.hhdz.barrage.utils.Constant;
import com.hhdz.barrage.utils.JSONTokener;
import com.hhdz.barrage.utils.Logcat;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

/**
 * Created by tangnan on 16-1-22.
 */
public class SocketService extends Service {

    private ServerSocket server = null;
    private HandlerThread mSocketReadThread;
    private Handler mSocketReadHandler;
    private Handler mUiHandler;

    private Context mContext = null;
    private ConnectivityManager mCM = null;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mContext = this;
        mCM = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
        mSocketReadThread = new HandlerThread("SOCKET:READ");
        mSocketReadThread.start();
        mSocketReadHandler = new Handler(mSocketReadThread.getLooper());
        mUiHandler = new Handler(Looper.getMainLooper());
        startListening();
        registerReceiver(mReceiver, new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"));
        Logcat.INFO("create service");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        try {
            server.close();
        } catch (Exception e) {
        }
        Logcat.INFO("stop service");
    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Logcat.INFO("onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    private void startListening() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                listen();
            }
        }).start();
    }

    private void stopListening() {
        if (server != null) {
            Logcat.INFO("stop listening...");
            try {
                server.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void listen() {
        try {
            Logcat.INFO("Wait connect...");
            if (server != null) {
                Logcat.INFO("Server exist");
                server.close();
            }
            server = new ServerSocket(9999);
            while (true) {
                final Socket socket = server.accept();
                Logcat.INFO("Get a connect...");
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        startReading(socket);
                    }
                }).start();
            }
        } catch (Exception e) {
            Logcat.INFO("Listener exception:"+e.toString());
            e.printStackTrace();
        }
    }

    private void toast(final String msg) {
        mUiHandler.post(new Runnable() {

            @Override
            public void run() {
                Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
            }

        });
    }

    public void startReading(final Socket socket) {
        Logcat.TRACE_CALL();
        Logcat.INFO("start reading");
        try {
            if (socket == null) {
                toast("ERROR: mSocket == null");
                return;
            }
            final InputStream stm = socket.getInputStream();
            final byte[] buffer = new byte[4096];
            while (true) {
                final int size = stm.read(buffer);
                if (size == -1) return;
                String string = new String(buffer,0,size);
                Logcat.DEBUG("read: " + string);
                JSONTokener token = new JSONTokener(string);
                ArrayList<Object> values = token.values();
                for (Object object : values) {
                    if (!(object instanceof JSONObject)) {
                        continue;
                    }
                    final JSONObject json = (JSONObject) object;
                    handleMsg(json);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            toast("ERROR: " + e.getMessage());
        } finally {
            disconnect(socket);
        }
    }

    public void disconnect(Socket socket) {
        Logcat.TRACE_CALL();
        if (socket == null) {
            toast("ERROR: mSocket == null");
            return;
        }
        try {
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void sendMsgBroadcast(String mac) {
        Intent intent = new Intent(Constant.ACTION_POP);
        intent.putExtra(Constant.EXTRA_MAC, mac);
        sendBroadcast(intent);
    }

    private void handleMsg(JSONObject json) {
        try {
            JSONArray array = json.getJSONArray("ds");
            for (int i = 0; i < array.length(); i++) {
                sendMsgBroadcast(array.getJSONObject(i).getString("da"));
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Logcat.TRACE_CALL(context, intent);
            String action = intent.getAction();
            if (action.equals("android.net.conn.CONNECTIVITY_CHANGE")) {
                final Bundle bun = intent.getExtras();
                for (String key : bun.keySet()) {
                    Logcat.DEBUG("key: " + key + ", " + bun.get(key));
                }
                if (mCM != null && mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected()) {
                    startListening();
                } else {
                    stopListening();
                }
            }
        }
    };

}
